package com.isyscore.os.driver;

import com.isyscore.os.driver.core.driver.*;
import com.isyscore.os.driver.core.enums.AttributeOperationEnum;
import com.isyscore.os.driver.core.enums.ItemTypeEnum;
import com.isyscore.os.driver.core.enums.SerialCommunicationCheck;
import com.isyscore.os.driver.core.utils.CommConf;
import com.isyscore.os.driver.core.utils.SerialPortHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BeiDouAccess extends DeviceDriverBase {
    private static final Logger logger = LoggerFactory.getLogger(BeiDouAccess.class);

    public static Map<String, DeviceInfo> deviceInfoDevIdMap = new ConcurrentHashMap<>();
    public static Map<String, Boolean> deviceIsOnlineMap = new ConcurrentHashMap<>();

    private SerialPortHelper objSerial;
    private Boolean serialIsOpened = false;


    public BeiDouAccess() {
        super("ff77ae16a8e54a77b1fac7224a5869c4",
                "",
                "",
                "1.0.0",
                "北斗gps定位驱动",
                "xyq",
                true,
                "北斗gps定位驱动",
                false);
    }

    public DriverFunctions initFunctions() {
        DriverFunctions driverFunctions = new DriverFunctions();

        DriverAttribute[] driverAttributes = new DriverAttribute[]{
                new DriverAttribute("positionInfo","位置信息",""),
        };

        DriverService[] driverServices = new DriverService[]{
                new DriverService("getPositionInfo","获取位置信息",""),
        };

        driverFunctions.setDriverServices(Arrays.asList(driverServices));
        driverFunctions.setDriverAttributes(Arrays.asList(driverAttributes));
        driverFunctions.setDriverEvents(Collections.emptyList());
        return driverFunctions;
    }

    public List<ConnectParam> initConnectParams() {
        return Collections.emptyList();
    }


    @Override
    public int initial(InitialParam driverParam) {
        logger.info("----------initial------------");
        objSerial = new SerialPortHelper();
        driverParam.getDeviceInfoList().forEach(deviceInfo -> {
            String devId = deviceInfo.getDevId();
            deviceInfoDevIdMap.put(devId, deviceInfo);
            
            COMParam com = driverParam.getComParam();
            String comName = com.getComName();
            logger.info("尝试打开串口设备：" + comName);
            //设置波特率，数据位，停止位，校验方式等
            CommConf objCommConf = new CommConf();
            objCommConf.setStrCommName(comName);
            objCommConf.setNBaudrate(com.getComBaudrate().getDesc());
            objCommConf.setNDataBit(com.getComData());
            objCommConf.setNParityBit(SerialCommunicationCheck.getNumber(com.getComCheck()));
            objCommConf.setNStopBit(com.getComStop());

            //打开串口设备
            if (!objSerial.openSerialPort(objCommConf)) {
                logger.error("打开串口设备失败： {} ", comName);
                notifyEvent(devId,CommonEventIdentifier.DEVICE_OFFLINE);
                deviceIsOnlineMap.put(devId,false);

            }else {
                logger.info("打开串口设备成功: CommName[" + comName + "]" + " BaudRate[" + com.getComBaudrate() + "]");
                serialIsOpened = true;
                notifyEvent(devId,CommonEventIdentifier.DEVICE_ONLINE);
                deviceIsOnlineMap.put(devId,true);

            }
        });

        return 0;
    }

    @Override
    public int unInitial() {
        logger.info("----------uninitial------------");
        if (objSerial != null) {
            objSerial.closeSerialPort();
            objSerial = null;
        }
        return 0;
    }
    public DriverResult checkConnectParams(List<ConnectParam> params) {
        return DriverResult.SUCCESS;
    }

    public DriverResult checkFunction(ItemTypeEnum functionType, String functionName, String functionParam) {
        return DriverResult.SUCCESS;
    }

    public boolean canPackage(TupleFrame frame, TslAttributeAction attributeAction) {
        return false;
    }

    public DriverResult accessAttribute(TupleFrame frame) {

        AttributeOperationEnum operation = frame.getOperation();
        List<TslAttributeAction> actions = frame.getAttributeActions();
        TslAttributeAction action = actions.get(0);
        String driverFunctionName = action.getDriverFunctionName();
        Map<String,Object> res;
        if (AttributeOperationEnum.READ == operation) {
            if (driverFunctionName.equals("位置信息")){
                res = getPositionInfo();
                for (TslAttributeAction ac : actions) {
                    ac.setValue(res);
                }
                return DriverResult.SUCCESS;
            }
            logger.error("驱动功能不存在");
            return DriverResult.NO_IMPLEMENT;


        }

        logger.error("驱动功能不存在");
        return DriverResult.NO_IMPLEMENT;

    }

    @Override
    public DriverResult accessService(TslServiceAction serviceAction) {
        String driverFunctionName = serviceAction.getDriverFunctionName();
        if (!driverFunctionName.equals("获取位置信息")){
            logger.error("驱动功能不存在");
            return DriverResult.NO_IMPLEMENT;
        }
        Map<String, Object> res = getPositionInfo();
        serviceAction.setOutputs(res);
        return DriverResult.SUCCESS;
    }

    private Map<String,Object> getPositionInfo() {
        Map<String, Object> positionInfo = new ConcurrentHashMap<>();
        Map<String, Object> GPGGA = new ConcurrentHashMap<>();
        Map<String, Object> GPVTG = new ConcurrentHashMap<>();
        byte[] response = sendAndRecv(1000);

        if (response != null){
            String strRes = new String(response);
            logger.info("收到响应报文：{}",strRes);
            String[] gpsInfo = strRes.split("\\$");

            for (String item :gpsInfo){
                if (item.startsWith("GPGGA")){
                    String [] splitList = item.split(",");
                    GPGGA.put("type",splitList[0]);
                    GPGGA.put("utcTime",splitList[1]);
                    String latitude = String.valueOf(Double.parseDouble(splitList[2]) * 0.01);
                    GPGGA.put("latitude",latitude);
                    GPGGA.put("latitudeDirection",splitList[3]);
                    String longitude = String.valueOf(Double.parseDouble(splitList[4]) * 0.01);
                    GPGGA.put("longitude",longitude);
                    GPGGA.put("longitudeDirection",splitList[5]);
                    GPGGA.put("gpsStatus",splitList[6]);
                    GPGGA.put("gpsCount",splitList[7]);
                    GPGGA.put("HDOP",splitList[8]);
                    GPGGA.put("altitude",splitList[9] + splitList[10]);
                    GPGGA.put("ellipsoid",splitList[11] + splitList[12]);
                }else if (item.startsWith("GPVTG")){
                    String [] splitList = item.split(",");
                    GPVTG.put("type",splitList[0]);
                    GPVTG.put("angleTrueNorth",splitList[1]+splitList[2]);
                    GPVTG.put("angleMagneticNorth",splitList[3]+splitList[4]);
                    GPVTG.put("speedHorizontalN",splitList[5]);
                    GPVTG.put("speedHorizontalKM",splitList[7]);
                }
            }
        }else{
            logger.info("response is null");

        }
        if (!GPGGA.isEmpty()){
            positionInfo.put("GPGGA",GPGGA);
        }
        if (!GPVTG.isEmpty()){
            positionInfo.put("GPVTG",GPVTG);
        }
        return positionInfo;
    }


    public byte[] sendAndRecv(int timeout) {
        byte[] res = null;
        try {
            if(!serialIsOpened){
                logger.error("串口未打开");
                return null;
            }
            res = objSerial.waitAndRead(timeout);

        } catch (Exception e) {
            logger.error(e.getMessage());
        }


        return res;
    }

    private void notifyEvent(String devId,String eventIdentifier) {
        TslEventAction action = new TslEventAction();
        action.setDevId(devId);
        action.setIdentifier(eventIdentifier);
        listener.onEvent(action);
    }


    public static void main(String[] args) throws IOException {
        BeiDouAccess beiDouAccess = new BeiDouAccess();
        beiDouAccess.exportDescFile(null);

        SerialPortHelper objSerial;
        objSerial = new SerialPortHelper();

        //设置波特率，数据位，停止位，校验方式等
        CommConf objCommConf = new CommConf();
        objCommConf.setStrCommName("COM1");
        //打开串口设备
        if (!objSerial.openSerialPort(objCommConf)){
            logger.error("打开串口设备失败");
        }

        byte[] response = objSerial.waitAndRead(1000);
        String strRes = new String(response);
        logger.info("收到响应报文：{}",strRes);
        String[] gpsInfo = strRes.split("\\$");

        System.out.println(1);

    }
}
